home *** CD-ROM | disk | FTP | other *** search
- Path: news.clark.net!not-for-mail
- From: gusty@clark.net (Harlan Messinger)
- Newsgroups: comp.lang.c++
- Subject: Re: C++ OO question (long)
- Date: 28 Feb 1996 21:59:11 GMT
- Organization: Clark Internet Services, Inc., Ellicott City, MD USA
- Message-ID: <4h2j7f$nek@clarknet.clark.net>
- References: <4h08uq$mve@madeline.INS.CWRU.Edu>
- NNTP-Posting-Host: explorer.clark.net
- Mime-Version: 1.0
- Content-Type: TEXT/PLAIN; charset=ISO-8859-1
- Content-Transfer-Encoding: 8bit
- X-Newsreader: TIN [UNIX 1.3 950726BETA PL0]
-
- Bryan Murphy (bf461@cleveland.Freenet.Edu) wrote:
- :
- :
- : Bellow is the program I wrote. It implements a class called
- : Matrix, which allocates memory on the heap for the storage of
- : a matrix of XxY dimensions. It also implements a copy constructor
- : for assignment, and a couple of different mathematical operations
- : to be performed on the matrix.
-
- "Implements a copy constructor for assignment": this is the answer to
- problem 1. Copy construction and assignment are separate operations. Even
- though
-
- Matrix M3 = M1 * M2;
-
- looks like assignment, it is instead a constructor invocation equivalent to
-
- Matrix M3(M1 * M2);
-
- and will use your copy constructor, which apparently works.
-
- When instead you have the following:
-
- Matrix M3;
- M3 = M1 * M2;
-
- the second line IS an assignment. But you haven't defined an assignment
- operator for your Matrix class. It happens that assignment, along with
- the empty copy constructor and the destructor, is an operation that the
- compiler will define by default if you don't provide a member function
- for it explicitly. But what the default assignment operator does is a
- member-by-member assignment.
-
- Let's look at what you're assigning to M3. It's a temporary Matrix that
- is the product of M1 and M2. Let's call it MT. MT has a member called
- MatrixData that points to an array that was dynamically allocated by the
- operator * function. However, only the pointer is a _member_ of MT. The
- matrix elements are in an allocated buffer somewhere out in space.
-
- Assigning MT to M3 by default sets M3.xdim = MT.xdim and M3.ydim =
- MT.ydim. No problem there. But then it sets M3.MatrixData =
- MT.MatrixData. In other words, M3 now has a pointer that points to the
- same buffer that MT points to. It hasn't allocated a buffer of its own.
-
- Once the assignment is finished, MT, being a temporary, disappears. Since
- you've provided a proper destructor, MT's destructor deletes
- MT.MatrixData, sending it back to the heap. But M3.MatrixData was
- pointing to the same array! Which means that M3.MatrixData is now
- pointing to garbage. And your program blows up.
-
- You can either:
-
- 1. Rely on the default assignment operator, but instead of
- having MatrixData be a pointer to a dynamically
- allocated block of memory, have it BE (not point to)
- array-type (a.k.a. vector) class whose constructor and
- destructor take care of allocation and deallocation
- automatically, and that has its own assignment operator.
- Have the constructor of Matrix initialize MatrixData.
-
- 2. Create your own assignment member function that includes
- the same data allocation feature as the copy constructor.
-
- Matrix &operator =(const Matrix &mat)
- {
- // Assign xdim and ydim.
- ...
- // Allocate a new buffer
- // to hold the data to be copied from mat.
- ...
- // Delete the array currently pointed to
- // by MatrixData, and then set MatrixData
- // to point to the new buffer.
- ...
- return *this; // usual operator = convention.
- }
-
- :
- : and I have another question related to this. When I define
- : the Matrix M3 and assign it right away, is the Default Blank
- : Constructor called, THEN the Copy Constructor? Or just the
- : copy constructor?
-
- Reviewing from above, the statement of the form
-
- Matrix M3 = M1 * M2;
-
- IS a call to the copy constructor. And when a class is constructed, only
- one of its constructors is called.
-
- Also, say the copy Constructor was called.
- : When the new data is copied over, is the Destructor called
- : before the copy constructor is used to copy the new data over?
-
- No, afterwards, but again, the point is that in your latter scenario the
- copy constructor ISN'T called because you're assigning, not constructing.
- And default assignment wasn't creating a buffer for M3.
-
-